package net.lovesrc.allin.jobs.backup;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import freemarker.template.Configuration;
import freemarker.template.Template;
import net.lovesrc.allin.biz.NotificationService;
import net.lovesrc.allin.biz.dida.*;
import net.lovesrc.allin.jobs.base.BaseJob;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

import java.io.StringWriter;
import java.time.LocalTime;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

@Component
@Profile("live")
public class DidaRideJob extends BaseJob {

    final AtomicLong atomicQty = new AtomicLong(0);

    @Override
    public void runOnce() throws Exception {
        long qty = atomicQty.getAndIncrement();
        logger.info("第{}次运行", qty);

        List<Ride> rides = rideService.getAll();
        for (Ride ride : rides) {
            safeRunOne(ride);
        }
    }

    @Override
    protected long intervalMilliseconds() {
        return TimeUnit.SECONDS.toMillis(5);
    }

    @Autowired
    private RideService rideService;

    @Autowired
    private NotificationService notificationService;

    @Autowired
    private Configuration configuration;

    private void safeRunOne(Ride ride) {
        if (!ride.isEnabled()) {
            return;
        }
        if (ride.getNextRunTime() == null) {
            rideService.nextRun(ride.getId(), 5);
            return;
        }
        if (ride.getNextRunTime() > System.currentTimeMillis()) {
            return;
        }
        try {
            logger.info("开始运行{}", ride.getName());
            long delaySecondsAfterNow = doRunOnce(ride);
            rideService.nextRun(ride.getId(), delaySecondsAfterNow);
            logger.info("完成运行{}，间隔{}秒后，再运行", ride.getName(), delaySecondsAfterNow);
        } catch (Exception e) {
            logger.error("run once error", e);
        }
    }

    /**
     * 返回下次运行间隔的秒数
     */
    private long doRunOnce(Ride ride) throws Exception {

        LocalTime nowTime = LocalTime.now();
        LocalTime rideSTime1 = ride.getTargetSTime1();
        LocalTime rideSTime2 = ride.getTargetSTime2();
        List<Listing> listings = rideService.getBookingRideListV2(ride);
        Set<ListingHolder> newHolders = Sets.newTreeSet(
                RideHelper.match(ride, listings)
                        .stream()
                        .filter((listingHolder) ->
                                jdbcTemplate.queryForObject("select count(1) from t_dida_ride_matched where id = ?", int.class, listingHolder.getOrigin().getId()) == 0
                        )
                        .collect(Collectors.toList())
        );
        if (newHolders.size() == 0) {
            Calendar calendar = Calendar.getInstance();
            int hour = calendar.get(Calendar.HOUR_OF_DAY);
            if (hour <= 6) {
                return 20 * 60;
            }
            if ((nowTime.isAfter(rideSTime1) || nowTime.isAfter(rideSTime1.plusHours(-2))) && nowTime.isBefore(rideSTime2)) {
                return RandomUtils.nextInt(5, 8);
            }
            return RandomUtils.nextInt(180, 300);
        }
        newHolders.forEach(listingHolder -> jdbcTemplate.update("insert into t_dida_ride_matched(id) values(?)", listingHolder.getOrigin().getId()));
        Map<String, Object> context = Maps.newHashMap();
        context.put("holders", newHolders);
        StringWriter stringWriter = new StringWriter();
        Template template = configuration.getTemplate("dida/listing-notice.ftl");
        template.process(context, stringWriter);
        String html = stringWriter.toString();
        stringWriter.close();
        String title;
        if (newHolders.size() == 1) {
            ListingHolder holder = newHolders.stream().findFirst().get();
            Poi fromPoi = holder.getOrigin().getFromPoi();
            Poi toPoi = holder.getOrigin().getToPoi();
            title = String.format("Ride(%s): %s - %s", ride.getName(), fromPoi.getShortAddress(), toPoi.getShortAddress());
        } else {
            title = String.format("Rides(%s, %s): %s - %s", newHolders.size(), ride.getName(), ride.getSName(), ride.getEName());
        }
        notificationService.email(NotificationService.LZQ_EMAIL, title, html);
        return RandomUtils.nextInt(5, 8);
    }

}
